/*
 *所有关于OrderForm类的业务代码应在此处编写
*可使用repository.调用常用方法，获取EF/Dapper等信息
*如果需要事务请使用repository.DbContextBeginTransaction
*也可使用DBServerProvider.手动获取数据库相关信息
*用户信息、权限、角色等使用UserContext.Current操作
*OrderFormService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter
*/
using Mercury.Core.BaseProvider;
using Mercury.Core.Extensions.AutofacManager;
using Mercury.Entity.DomainModels;
using System.Linq;
using Mercury.Core.Utilities;
using System.Linq.Expressions;
using Mercury.Core.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
using Mercury.Order.IRepositories;
using System.Threading.Tasks;
using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
using System;
using Microsoft.VisualBasic;
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
using Mercury.Core;
using System.Collections.Generic;
using Mercury.Core.ManageUser;
using static Dapper.SqlMapper;
using Mercury.Core.Enums;
using Mercury.Core.Configuration;
using Mercury.Core.Common;

namespace Mercury.Order.Services
{
    public partial class OrderFormService
    {
        private WebResponseContent _responseContent = new WebResponseContent();
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IOrderFormRepository _repository;//访问数据库

        [ActivatorUtilitiesConstructor]
        public OrderFormService(
            IOrderFormRepository dbRepository,
            IHttpContextAccessor httpContextAccessor
            )
        : base(dbRepository)
        {
            _httpContextAccessor = httpContextAccessor;
            _repository = dbRepository;
            //多租户会用到这init代码，其他情况可以不用
            //base.Init(dbRepository);
        }

        /// <summary>
        /// 同步计划单逻辑
        /// </summary>
        /// <returns></returns>
        public async Task<WebResponseContent> SyncPlannedOrder()
        {
            return _responseContent.OK("同步成功", DateTime.Now);
        }

        /// <summary>
        /// 计算计划单，生成领料单
        /// </summary>
        /// <param name="orderNo">计划单单号</param>
        /// <returns></returns>
        public async Task<WebResponseContent> ComputedPlannedOrder(string orderNo)
        {
            #region 1.0 获取计划单
            var order = await _repository.FindFirstAsync(c => c.Id == orderNo);
            if (order == null)
                return _responseContent.Error("未找到该计划单！");

            if (order.Status.HasValue && order.Status != 0)
                return _responseContent.Error("该计划单已处理！");

            #endregion

            #region 2.0 先删除已生成的领料单

            var storesRequisition = (from s in _repository.DbContext.Set<StoresRequisitionOrder>().Where(c => c.OrderNumber == order.OrderNumber).ToList()
                                     join b in _repository.DbContext.Set<StoresRequisition>().Where(c => c.DeletionFlag != 1).ToList()
                                     on s.SRId equals b.Id into d
                                     select new { s.OrderNumber }).FirstOrDefault();
            if (storesRequisition != null)
                return Response.Error("该计划单已生成领料清单，不可以重新计算！");

            var deleteMaterialRequisition = await _repository.FindAsync<MaterialRequisition>(c => c.OrderNumber == order.OrderNumber && c.DeletionFlag != 1);
            if (deleteMaterialRequisition.Any())
            {
                if (deleteMaterialRequisition.Any(c => c.State == 1))
                    return Response.Error("领料单已打印，请勿重复计算！");
                var type = typeof(MaterialRequisition);
                var deleteProperty = type.GetProperty(AppSetting.DeletionFlagField);
                var listField = type.GetDeletionFileds();

                foreach (var item in deleteMaterialRequisition)
                {
                    item.SetModifyDefaultVal();
                    item.DeletionFlag = 1;
                    repository.Update(item, listField.ToArray());
                }

                //#region 回滚返回料状态
                //var ids = deleteMaterialRequisition.Select(c => c.Id).ToList();
                //var details = _repository.DbContext.Set<MaterialRequisitionDetailed>().Where(c => string.IsNullOrEmpty(c.MaterialId) && ids.Contains(c.MRId));
                //var retrunMaterial = _repository.DbContext.Set<ReturnedMaterial>().Join(details, t => new { t.ProductNo, BatchNumber = t.Category }, s => new { ProductNo = s.MaterialName, s.BatchNumber }, (t, s) => new ReturnedMaterial
                //{
                //    Id = t.Id,
                //    State = t.State
                //}).ToList();

                //foreach (var item in retrunMaterial)
                //{
                //    if (item.State != 9)
                //        continue;
                //    item.State = 1;
                //    repository.Update(item, new string[] { "State" });
                //}
                //if(retrunMaterial.Any())
                //repository.DbContext.SaveChanges();
                //#endregion

            }
            #endregion

            var requiredWeight = 0d;
            if (!double.TryParse(order.RequiredWeight, out requiredWeight))
                return Response.Error($"计划单需求重量【{order.RequiredWeight}】配置异常！！");
            var response = await order.SteelGrade.MaterialCalculation(order.OrderNumber, requiredWeight, _repository, computedRate: AppSetting.Rate);

            if (!response.Item1)
                return Response.Error(response.Item2);

            #region 3.0 生成领料单
            var nowDate = DateTime.Now;
            var no = repository.DbContext.Set<MaterialRequisition>().Count(c => c.CreateDate >= nowDate.Date && c.CreateDate < nowDate.Date.AddDays(1)) + 1;
            var batchNo = $"{nowDate.ToString("yyyyMMdd")}#{no.ToString().PadLeft(6, '0')}";

            var id = Guid.NewGuid().ToString();
            var materialRequisition = new MaterialRequisition()
            {
                Id = id,
                OrderNumber = order.OrderNumber,
                MRNumber = order.Id,
                DeletionFlag = 0,
                IssuanceTime = DateTime.Now,
                BatchingNo = batchNo,
                State = 0
            };
            materialRequisition.SetCreateDefaultVal();
            var list = response.Item3.Select(c => new MaterialRequisitionDetailed()
            {
                MaterialId = c.MaterialId,
                MaterialName = c.MaterialName,
                RequiredWeight = c.RequiredWeight.ToString(),
                Id = Guid.NewGuid().ToString(),
                MRId = id,
                BatchNumber = c.BatchNO
            }).ToList();
            #endregion

            Response = _repository.DbContextBeginTransaction(() =>
             {
                 _repository.DbContext.Entry(materialRequisition).State = EntityState.Added;
                 list.ForEach(e =>
                 {
                     e.SetCreateDefaultVal();
                     _repository.DbContext.Entry(e).State = EntityState.Added;
                 });
                 repository.DbContext.SaveChanges();
                 Response.OK(ResponseType.SaveSuccess);
                 return Response;
             });
            return Response;
        }
    }
}
